package com.beiding.jsonanalyzer.flow;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 流对象,全局通用
 * 本身可注册观察者事件
 */
public class Flow {


    /**
     * 添加观察者
     *
     * @param type
     * @param eventListener
     * @param <E>
     */
    public <E> void addListener(Class<E> type, EventListener<E> eventListener) {

        synchronized (getEventListenerMap()) {
            Map<Class<E>, List<EventListener<E>>> eventListenerMap = getEventListenerMap();

            List<EventListener<E>> eventListeners = eventListenerMap.computeIfAbsent(type, k -> Collections.synchronizedList(new ArrayList<>()));
            eventListeners.add(eventListener);
        }

    }

    /**
     * 移除观察者
     *
     * @param type
     * @param eventListener
     * @param <E>
     */
    public <E> void removeListener(Class<E> type, EventListener<E> eventListener) {
        synchronized (getEventListenerMap()) {
            Map<Class<E>, List<EventListener<E>>> eventListenerMap = getEventListenerMap();
            List<EventListener<E>> eventListeners = eventListenerMap.get(type);
            if (eventListeners != null) {
                eventListeners.remove(eventListener);
                if (eventListeners.size() == 0) {
                    eventListenerMap.remove(type);
                }
            }
        }
    }

    /**
     * 获取某类型的所有观察者
     *
     * @param type
     * @param <E>
     * @return
     */
    public <E> List<EventListener<E>> getListeners(Class<E> type) {
        Map<Class<E>, List<EventListener<E>>> eventListenerMap = getEventListenerMap();
        List<EventListener<E>> eventListeners = eventListenerMap.get(type);
        if (eventListeners == null) {
            return Collections.emptyList();
        }
        return Collections.unmodifiableList(eventListeners);
    }

    /**
     * 提交事件
     *
     * @param event
     */
    public void emit(Object event) {
        synchronized (getEventListenerMap()) {

            //不能为空
            Class type = event.getClass();
            Map<Class<Object>, List<EventListener<Object>>> eventListenerMap = getEventListenerMap();
            for (Map.Entry<Class<Object>, List<EventListener<Object>>> entry : eventListenerMap.entrySet()) {
                Class tp = entry.getKey();

                //执行动作
                if (tp.isAssignableFrom(type)) {
                    List<EventListener<Object>> value = entry.getValue();
                    for (EventListener<Object> listener : value) {
                        try {
                            listener.on(event);
                        } catch (Exception e) {
                            //只打印异常,不会终止流程
                            e.printStackTrace();
                        }
                    }
                }
            }

        }
    }

    private Map eventListenerMap = new ConcurrentHashMap();

    private <E> Map<Class<E>, List<EventListener<E>>> getEventListenerMap() {
        return eventListenerMap;
    }

}
